////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//                                                                                                                            //
//                                                         WNProject                                                          //
//                                                                                                                            //
//            This file is distributed under the BSD 2-Clause open source license. See License.txt for details.               //
//                                                                                                                            //
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#pragma once

#ifndef __WN_SCRIPTING_TYPE_ELEMENT_H__
#define __WN_SCRIPTING_TYPE_ELEMENT_H__

#include "WNScripting/inc/WNIdentifierElement.h"

#include <vector>

namespace llvm {
    class Type;
    class StructType;
};

namespace WNScripting {
    enum WNVariableType {
        eWNTypeInvalid = 0,
        eWNTypeInt,
        eWNTypeFloat,
        eWNTypeBool,
        eWNTypeArray,
        eWNTypeStruct,
        eWNTypeChar,
        eWNTypeString,
        eWNTypeMAX,
        eWNTypeUser
    };

    template<typename Type> struct StructTest {
        static WN_BOOL Test(const Type& _first, const Type& _second) {
            return(_first == _second);
        }
    };

    template<typename Tit, typename Type, typename S> Tit
        WNFind(Tit _begin, Tit _end, const Type& _val) {

        Tit i;

        for(i = _begin; i != _end; ++i) {
            if (S::Test(*i, _val)) {
                break;
            }
        }

        return(i);
    }

    struct __WNTypeElementInternal {
        WNVariableType mType;
        WNIdentifierElement mUserTypeName;

        union {
            llvm::Type* mLlvmType;
            llvm::StructType* mStructType;
        };

        __WNTypeElementInternal* mSubType;
        std::vector<__WNTypeElementInternal*>* mStructTypes;
        std::vector<WNIdentifierElement>* mSubTypeNames;
        WN_BOOL mIsStruct;
        WN_BOOL mForceHeap;
    };

    typedef __WNTypeElementInternal* WNTypeElement;

    class WNUserTypeCompare {
    public:
        WNUserTypeCompare(WNTypeElement _testType) : mType(_testType) {}

        WN_BOOL operator() (const WNTypeElement first) {
            return(mType->mUserTypeName == first->mUserTypeName);
        }

    private:
        WNTypeElement mType;
    };
}
#endif // __WN_SCRIPTING_TYPE_ELEMENT_H__